# -*- coding: utf-8 -*-

import json
from datetime import datetime, timedelta

from django.utils.decorators import method_decorator
from django.utils.encoding import smart_unicode
from django.views.decorators.http import require_GET, require_POST
from django.views.generic import TemplateView

from async import async_job
from common.admin import db as user_db
from common.channel import admin_db as channel_admin_db
from common.channel import db as channel_db
from common.channel.channel_map import CHANNEL_HANDLER
from common.export.handler import export_data_start, get_export_status_by_user_id
from common.order import admin_db as order_db
from common.order import db as order_db1
from common.utils import track_logging
from common.utils.api import check_params
from common.utils.api import token_required
from common.utils.decorator import response_wrapper, safe_wrapper
from common.utils.tz import (
    utc_to_local_str
)
from common.utils.api import get_location

_LOGGER = track_logging.getLogger(__name__)


class PayOrderView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        # todo  解决\ufeff
        # query_dct['service'] = {"$neq": 'test'}
        cond = user_db.get_mchids_filter_by_user(req.user_id)
        if cond and not query_dct.get('mch_id', ''):
            query_dct['mch_id'] = cond
        user_db.filter_user_channels(req.user_id, query_dct, 'channel_id')
        _LOGGER.info('PayOrderView get mchs: %s', query_dct)
        export = query_dct.pop('$export', None)
        if export:
            export_id = export_data_start(req.user_id, json.dumps(query_dct), 'ewqwer')
            async_job.export_data.delay(export_id)
            return {'export_id': export_id}

        if query_dct.get('created_at', None) is None and query_dct.get('updated_at', None) is None:
            tmp_time = datetime.utcnow() + timedelta(days=-30)
            query_dct['created_at'] = {"$gte": tmp_time.strftime("%Y-%m-%d %H:%M:%S")}

        items, total_count = order_db.list_order(query_dct)

        resp_items = []
        for item in items:
            data = item.as_dict()
            data['payed_at'] = utc_to_local_str(data['payed_at'])
            data['created_at'] = utc_to_local_str(data['created_at'])
            data['updated_at'] = utc_to_local_str(data['updated_at'])
            if data['mch_create_ip']:
                data['location'] = get_location(data['mch_create_ip'])
            else:
                data['location'] = ''
            data['id'] = str(data['id'])
            if export:
                resp_items.append([data.get(x, '-') for x in header])
            else:
                resp_items.append(data)

        overview, chn_ids = order_db.get_order_overview(query_dct)
        chns = channel_admin_db.get_channels_in_ids(chn_ids)
        p_info = dict()
        for chn in chns:
            p_info[chn.id] = {
                'name': chn.name,
                'service_name': chn.service_name,
                'mch_id': chn.mch_id,
                'rate': chn.rate,
            }
        total_money = 0.0
        for o in overview:
            chn_id = o['channel_id']
            total_money += o.get('total', 0)
            if chn_id not in p_info:
                continue
            chn_info = p_info[chn_id]
            o.update({
                'channel_name': chn_info['name'],
                'service_name': chn_info['service_name'],
                'mch_id': chn_info['mch_id'],
                'rate': chn_info['rate'],
            })
            if chn_info.get('rate') and o.get('total', 0):
                o['real_income'] = '%.2f' % float(o.get('total', 0) * (100.0 - chn_info.get('rate')) / 100.0)
            else:
                o['real_income'] = u'费率或总金额为空'

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'overview': overview,
                'size': len(resp_items), 'total_count': total_count, 'total_money': total_money}

    def post(self, req):
        param_dct = json.loads(req.body)
        order_db.upsert_order(base=param_dct.get('base'))
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(PayOrderView, self).dispatch(*args, **kwargs)


class SinglePayOrderView(TemplateView):
    def get(self, req, order_id):
        order = order_db.get_order(id=int(order_id))
        data = order.as_dict()
        data['id'] = order_id
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        return data

    def post(self, req, order_id):
        return self.put(req, order_id)

    def put(self, req, order_id):
        query_dct = json.loads(smart_unicode(req.body))
        order_db.upsert_order(query_dct, int(order_id))
        return {}

    def delete(self, req, order_id):
        order_db.delete_order(int(order_id))
        _LOGGER.info('delete order: %s, user: %s', order_id, req.user_id)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SinglePayOrderView, self).dispatch(*args, **kwargs)


@require_POST
@response_wrapper
@token_required
def fresh(req, order_id):
    order_id = int(order_id)
    order = order_db.get_order(id=order_id)
    if order.status != 0:  # 支付成功或失败，重新回调
        async_job.notify_mch.delay(order_id)
    else:
        # 未支付，调用通道接口查询订单状态
        chn = channel_admin_db.get_channel(order.channel_id)
        chn_info = json.loads(chn.info)
        app_id = chn_info.get('app_id')
        chn_handler = CHANNEL_HANDLER[order.channel_type]
        chn_handler.query_charge(order, app_id)
    return {}


@require_POST
@response_wrapper
@token_required
@safe_wrapper
def make_success(req, order_id):
    order_id = int(order_id)
    query_dct = json.loads(smart_unicode(req.body))
    check_params(query_dct, ('reason', 'amount'))
    if query_dct['reason'].replace(' ', '') == '':
        return {'result': 'error', 'msg': 'reason can not be null'}
    order_db1.set_pay_success(order_id, query_dct['reason'], amount=query_dct['amount'])
    async_job.notify_mch.delay(order_id)
    order_db1.record_manual_order(order_id, req.user, query_dct['reason'])
    return {'id': order_id, 'result': 'success'}


@require_GET
@response_wrapper
@token_required
def get_export_status(req):
    return get_export_status_by_user_id(req.user_id).as_dict()


@require_GET
@response_wrapper
@token_required
def get_manual_orders(req):
    query_dct = req.GET.dict()
    cond = user_db.get_mchids_filter_by_user(req.user_id)
    if cond and not query_dct.get('mch_id', ''):
        query_dct['mch_id'] = cond

    items, total_count = order_db.list_manual_order(query_dct)
    resp_items = []
    for item in items:
        data = item.as_dict()
        data['payed_at'] = utc_to_local_str(data['payed_at'])
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        data['id'] = str(data['id'])
        resp_items.append(data)
    return {'list': resp_items, 'page': query_dct.get('$page', 1),
            'size': len(resp_items), 'total_count': total_count}


class RepeatOrderView(TemplateView):

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def get(self, req):
        query_dct = req.GET.dict()
        items, total_count = channel_db.list_repest_no(query_dct)
        resp_items = []
        for item in items:
            data = item.as_dict()
            data['order_no'] = str(data['order_no'])
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'total_count': total_count, 'size': len(resp_items)}


@require_POST
@response_wrapper
@token_required
def handle_repeat_order(req):
    query_dct = req.POST.dict()
    _LOGGER.info('handle_repeat_order: %s', query_dct)
    channel_db.handle_repeat_order(query_dct['id'], req.user.nickname, req.user.id, msg=query_dct['msg'])
    return {'result': 'success'}
